/*
 * Objekt.h
 *
 *  Created on: Feb 11, 2011
 *      Author: alki
 */

#ifndef OBJEKT_H_
#define OBJEKT_H_

#include "../math/Vektor.h"
#include "../math/Gerade.h"
#include "../manager/MaterialManager.h"
#include "Material.h"
#include "Textur.h"
#include <stdlib.h>
#include <vector>

/**
 * Klasse Vertex: definiert einen Punkt im Raum
 */
class VERTEX {
public:
	Vektor pos; // Position
	Vektor n; // Normalenvektor
	int mat; // Material
	float u; // baryzentrische Koordinaten der Textur
	float v;
};

/**
 * Klasse Triangle: definiert Dreiecke des Modells
 */
class TRIANGLE {
public:
	TRIANGLE() {points[0]=points[1]=points[2]=0;}
	TRIANGLE(unsigned int a,unsigned int b,unsigned int c) {points[0]=a;points[1]=b;points[2]=c;}
	unsigned int points[3];
};

/**
 * Klasse Objekt: repräsentiert das Objekt
 */
class Objekt {
public:
	Objekt();
	virtual ~Objekt();

	void setTest3();
	void setTest4();

	void setWand(FARBE f,bool tex=false);
	void setLampe(FARBE f);
	void setSpiegel();/**/

	/**
	 * berechnet die Vertex-Normalen und den maximalen Radius
	 */
	void CalcVNormals();
	void CalcRadius();
	void CalcPosition();

	void setPosition(float x,float y,float z) { this->m_position.set(x,y,z); }
	void setRotation(float x,float y,float z) { this->m_rotX=x; this->m_rotY=y; this->m_rotZ=z; }

	Vektor getPosition() const { return this->m_position; }
	float getRotX() const { return this->m_rotX; }
	float getRotY() const { return this->m_rotY; }
	float getRotZ() const { return this->m_rotZ; }

	/**
	 * überprüft auf Schnitt mit Gerade
	 */
	bool Intersects(const Gerade &ray,Vektor *schnittpunkt=NULL,float *r=NULL,float *s=NULL) const;

	VERTEX getVertex(int index) const { return this->m_vertices[index]; }
	TRIANGLE getTriangle(int index) const { return this->m_triangles[index]; }
	unsigned int getVertexCount() const { return this->m_vertices.size(); }
	unsigned int getTriangleCount() const { return this->m_triangles.size(); }

	/**
	 * berechnet den Normalenvektor bzw. das Material einer Position auf dem Objekt
	 */
	Vektor getNormal(const Gerade &ray,const Vektor &pos) const;
	Material getMaterial(const Gerade &ray,const Vektor &pos,const MaterialManager &matman) const;

	float getRadius() const { return this->m_radius; }

	/**
	 * testet, ob das Objekt leuchtet bzw. ob ein Punkt auf dem Objekt liegt
	 */
	bool leuchtet() const;
	bool Point(Vektor p) const;

	/**
	 * gibt die Ausdehnung des Modells zurück
	 */
	Vektor getMaxRad() const;
	Vektor getMin() const;
	Vektor getMax() const;

	void AddVertex(VERTEX vert);
	void AddVertices(vector<VERTEX> verts);
	void AddMaterialManager(MaterialManager *matman) { m_matman=matman; }

	void AddTriangle(TRIANGLE tri);

	int index;

private:
	/**
	 * Punkte des Modells
	 */
	vector<VERTEX> m_vertices;

	/**
	 * Dreiecke des Modells
	 */
	vector<TRIANGLE> m_triangles;

	/**
	 * Texturen des Modells
	 */
	vector<Textur> m_texturen;

	MaterialManager *m_matman;

	/**
	 * Position und Drehung der Achsen des Modells
	 */
	Vektor m_position;
	float m_rotX;
	float m_rotY;
	float m_rotZ;

	/**
	 * maximaler Radius zu r schnelleren Berechnung von Kollisionen
	 */
	float m_radius;

	/**
	 * liefert zu einer Position das zugehörige Dreieck mit baryzentrischen Koordinaten der Lage
	 */
	int getTri(const Gerade &ray,const Vektor &pos,float *r,float *s) const;
	int getTri(const Vektor &pos,float *r,float *s) const;
};

#endif /* OBJEKT_H_ */
